package pluginMain;

import java.util.logging.Logger;

import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.inventory.CraftItemEvent;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.ServicePriority;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.event.player.PlayerExpChangeEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerLevelChangeEvent;
import org.bukkit.event.player.PlayerRespawnEvent;

import skill.Skill;
import skill.SkillBase.SkillType;
import skill.SkillManager;

public class SP extends JavaPlugin implements Listener {
	// Plugins instance
	public static Plugin instance;
	public final String PLUGIN_NAME = "RemiliaNetwork SP";
	// For console logger
	private static Logger CONSOLE_LOGGER;
	// Skills Save
	public static SkillManager sm;
	// Configs
	public Configer skills;
	// Const
	public static final String PlayerDataFolder = "Player";
	// Scoreborad update
	public static BAKAScoreboard instanceSB;
	public static final String SCORE_EXP = "&2经验值";
	public static final String SCORE_HLH = "&2生命值";
	public static void LOGCONSOLE(String msg) {
		CONSOLE_LOGGER.info(msg);
	}

	@Override
	public void onEnable() {
		// create instance now
		instance = this;
		sm = new SkillManager(instance);
		CONSOLE_LOGGER = instance.getLogger();
		// load skills form config files
		skills = new Configer(this, "skills.yml");
		// release example file
		Configer.ReleaseFileIfNotExist(this, "example.txt");
		// instanceSB load
		instanceSB = (BAKAScoreboard) getServer().getPluginManager().getPlugin("BAKAScoreboard");

		int id;
		String name;
		SkillType t;
		double effect;
		// init skills first
		
		for (String s : skills.getKeys(false)) {
			id = skills.getInt(s + ".id");
			name = skills.getString(s + ".name");
			t = SkillType.valueOf(skills.getString(s + ".type"));
			effect = skills.getDouble(s + ".effect");
			sm.AddNewSkill(id, name, t, effect);
		}
		LOGCONSOLE("Loaded " + sm.getSkillCount() + " Skill(s)");

		LOGCONSOLE("Registering Service...");
		// register serivces
		getServer().getServicesManager().register(SkillManager.class, sm, instance, ServicePriority.Normal);
		getServer().getPluginManager().registerEvents(this, this);
		LOGCONSOLE(PLUGIN_NAME + " has been started.");
	}

	@Override
	public void onDisable() {
		LOGCONSOLE(PLUGIN_NAME + " has been disabled.");
	}

	@SuppressWarnings("deprecation")
	@Override
	public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
		if (!(sender instanceof Player)) {
			if (args.length == 3) {
				return sm.getPlayerSkills(getServer().getPlayer(args[2])).learnNextLevel(args[1]);
			}
			if (args.length == 2) {
				return sm.showOtherPlayerSkill(sender, args[1]);
			}
		}

		if (label.toLowerCase().equals("splvl")) {
			switch (args[0].toLowerCase()) {
			case "learn":
				if (args.length == 1) {
					sm.showSkills((Player) sender);
					return true;
				}
				if (!sender.hasPermission("Level.Admin")) {
					if (sender.hasPermission("Level.VIP") || CommandColdDownManager.test(sender, args[0])) {
						return sm.getPlayerSkills(((Player) sender)).learnNextLevel(args[1]);
					} else {
						sender.sendMessage("你学得太快了（指令冷却中……）");
						return false;
					}
				} else {
					sender.sendMessage("管理员权限传递成功!");
					sm.getPlayerSkills(((Player) sender)).learnNextLevelAdmin(args[1], ((Player) sender));
				}

				break;
			default:
				sm.showLevels((Player) sender);
			}

		}
		return true;
	}

	@EventHandler
	public void onPlayerJoin(PlayerJoinEvent event) {
		Player p = ((PlayerJoinEvent) event).getPlayer();
		LOGCONSOLE("Loading " + p.getName() + " Skills...");
		sm.AddNewPlayer(p);
		// add player max health
		// p.setMaxHealth(20);
		// it done in RPGHelath plugin
		double baseHealth  = p.getMaxHealth();
		for (Skill k : sm.getPlayerSkills(p).getSkillByType(SkillType.Health)) {
			baseHealth += (k.getLevel() * k.getSkillBase().getSkillPerLevelEffect());
		}
		p.setMaxHealth(baseHealth);
		LOGCONSOLE("Loaded player " + sm.getPlayerSkills(p).getOwner().getName() + " skills data.");
		SP.instanceSB.showInfo(p, SP.SCORE_EXP, p.getTotalExperience());
		SP.instanceSB.showInfo(p, SCORE_HLH, (int) p.getMaxHealth());
	}

	@EventHandler
	public void onPlayerGainExp(PlayerExpChangeEvent event) {
		SP.instanceSB.showInfo(event.getPlayer(), SP.SCORE_EXP, event.getPlayer().getTotalExperience());
	}

	@EventHandler
	public void onPlayerTake(PlayerLevelChangeEvent event) {
		SP.instanceSB.showInfo(event.getPlayer(), SP.SCORE_EXP, event.getPlayer().getTotalExperience());
	}

	@EventHandler
	public void onPlayerRespawn(PlayerRespawnEvent event) {
		Player p = ((PlayerRespawnEvent) event).getPlayer();
		double baseHealth  = p.getMaxHealth();
		for (Skill k : sm.getPlayerSkills(p).getSkillByType(SkillType.Health)) {
			baseHealth += (k.getLevel() * k.getSkillBase().getSkillPerLevelEffect());
		}
		p.setMaxHealth(baseHealth);
		SP.instanceSB.showInfo(event.getPlayer(), SP.SCORE_EXP, event.getPlayer().getTotalExperience());
	}

	@EventHandler
	public void onEntityDamageByEntityEvent(EntityDamageByEntityEvent e) {
		if (e.getDamager() instanceof Player) {
			Player source = (Player) e.getDamager();

			// check weapon stable
			if (!WeaponRestrictor.Stable(source, source.getItemInHand())) {
				e.setCancelled(true);
				return;
			}

			// add damage
			double damageAdd = 0;
			// calc how damage should add
			for (Skill k : sm.getPlayerSkills(source).getSkillByType(SkillType.Power))
				damageAdd += k.getLevel() * k.getSkillBase().getSkillPerLevelEffect();
			// add into damage
			e.setDamage(e.getDamage() + damageAdd);

			// calc weapon druaibility
			for (Skill k : sm.getPlayerSkills(source).getSkillByType(SkillType.Skill)) {
				float percent = k.getLevel() > 50 ? 50 : k.getLevel();
				if (Math.random() * 100f < percent) {
					// within percent of random area
					source.getItemInHand().setDurability((short) (source.getItemInHand().getDurability() + 2));
					break;
				}
			}
		}
	}

	@EventHandler
	public void onPlayerCraft(CraftItemEvent e) {
		if (!WeaponRestrictor.Stable((Player) e.getWhoClicked(), e.getCurrentItem())) {
			e.setCancelled(true);
		}
	}
}
